﻿using System;
using System.Drawing;
using System.Globalization;
using HtmlAgilityPack;
using Yah.Parser;

namespace YahContent
{
    /// <summary>
    ///sử dụng thư viện nguồn mở http://htmlagilitypack.codeplex.com/ để load HTMLDocument
    ///sử dụng dự án nguồn mở http://www.codeproject.com/Articles/35978/Reading-Image-Headers-to-Get-Width-and-Height để đọc header của ảnh 
    ///.net ver 4.5
    ///Throw Exeption nếu gặp lỗi !!!
    /// </summary>
    public class DataExtractor
    {
        public static string UserAgent = "Mozilla/5.0 (compatible; Googlebot/2.1; +http://www.google.com/bot.html)";
        //Google bot
        //private static string _userAgent = "Mozilla/4.0 (compatible; MSIE 8.0; Windows NT 6.1)";//IE 8
        public HtmlDocument HtmlDocument = null;
        private readonly string _url;
        private readonly ImageProcess _imageProcess;

        public DataExtractor(string url)
        {
            if (!url.Contains("://")) url = "http://" + url;
            _url = url;
            try
            {
                //tải trang web về và load HtmlDocument
                HtmlDocument = HtmlParser.GetHtmlDoc(url, out _url, out _allContent);
            }
            catch
            {
                throw new Exception("Quá trình tải trang web về bị lỗi, lỗi này có thể do kết nối internet có vấn đề");
            }
            ProcessHtmlDocument();
            _imageProcess = new ImageProcess(_url, HtmlDocument);
        }

        /// <summary>
        /// Hàm tiền xử lý htmldocument loại bỏ nhưng thành phần không cần thiết như là script, các thẻ comment
        /// Loại bỏ thuộc tính của các thẻ font
        /// </summary>
        private void ProcessHtmlDocument()
        {
            var listNode1 = HtmlDocument.DocumentNode.SelectNodes("//script");
            if (listNode1 != null)
            {
                foreach (var node in listNode1)
                {
                    node.Remove();
                }
            }
            var listNode2 = HtmlDocument.DocumentNode.SelectNodes("//comment()");
            if (listNode2 != null)
            {
                foreach (var node in listNode2)
                {
                    node.Remove();
                }
            }
            var listNode3 = HtmlDocument.DocumentNode.SelectNodes("//iframe");
            if (listNode3 != null)
            {
                foreach (var node in listNode3)
                {
                    node.Remove();
                }
            }
            HtmlDocument.DocumentNode.InnerHtml =
                HtmlDocument.DocumentNode.InnerHtml.Replace("\r", "").Replace("\n", "").Replace("\t", "");
        }

        /// <summary>
        /// những ảnh có kich thước nhỏ hơn hoặc bằng gia trị này được coi là ảnh nhỏ
        /// </summary>
        private Size _sizeOfSmallImage = new Size(150, 150);

        private readonly string _allContent;


        public DataAttri Callpoint(HtmlNode parent)
        {
            var res = new DataAttri {TextLenght = parent.InnerText.Length};


            foreach (var node in parent.Descendants())
            {
                //-----------
                if (node.Name.ToLower() == "img")
                {
                    node.Attributes["src"].Value = _imageProcess.GetUrlFormSrc(node.Attributes["src"].Value);
                    var sizeImage = new Size(0, 0);
                    if (node.Attributes["w_h1"] != null)
                    {
                        sizeImage.Width = Convert.ToInt32(node.Attributes["w_h1"].Value);
                        sizeImage.Height = Convert.ToInt32(node.Attributes["w_h2"].Value);
                    }
                    else
                    {
                        sizeImage = _imageProcess.GetSizeOfImgNode(node);
                        node.Attributes.Add("w_h1", sizeImage.Width.ToString(CultureInfo.InvariantCulture));
                        node.Attributes.Add("w_h2", sizeImage.Height.ToString(CultureInfo.InvariantCulture));
                    }
                    if (sizeImage.Width > _sizeOfSmallImage.Width && sizeImage.Height > _sizeOfSmallImage.Height)
                    {
                        res.NumberOfBigImage++;
                        res.NumberOfImage += (sizeImage.Width + sizeImage.Height)%6000;
                    }
                    else
                    {
                        if (sizeImage.Width < 25 && sizeImage.Height < 25)
                        {
                            res.NumberOfTag++;
                        }
                        else
                        {
                            res.NumberOfSmallImage++;
                            res.NumberOfImage -= sizeImage.Width*sizeImage.Height;
                        }
                    }
                }
                //----------
                if (
                    "<em><br><i><u><b><h1><h2><h3><h4><h5><h6><strong><p><ins><small><sup><sub><big><del>"
                        .Contains(node.Name.ToLower()))
                {
                    res.NumberOfTag++;
                }
                //----------
                if ("<li><u><ol><b><strong>".Contains("<" + node.Name.ToLower() + ">") &&
                    GetSentences(node.InnerText) == 0)
                {
                    res.NumberOfTitle += node.InnerText.Length;
                }
                //----------
                if ("<input><textarea>".Contains("<" + node.Name.ToLower() + ">"))
                {
                    res.NumberOfInput++;
                }
                //---------
                if (node.Name.ToLower() == "#text" && node.InnerText.Length > 100)
                {
                    res.NumberOfLongText++;
                }
            }
            /////////////////////////
            foreach (var node in parent.ChildNodes)
            {
                if (((node.Name.ToLower() == "#text" || node.Name.ToLower() == "p") &&
                     GetSentences(node.InnerText.Trim()) >= 2))
                {
                    res.NumberOfParagraph++;
                }
                if (node.InnerText.Length > 100)
                {
                    res.NumberOfTextParagraph++;
                }
            }
            res.NumberOfSum = (res.NumberOfParagraph*parent.XPath.Length + res.NumberOfTextParagraph*30 +
                               res.NumberOfLongText*20 +
                               res.NumberOfImage + parent.XPath.Length + res.TextLenght/parent.XPath.Length +
                               res.NumberOfBigImage*20 +
                               res.NumberOfTag*5 -
                               res.NumberOfTitle - res.NumberOfSmallImage*parent.XPath.Length -
                               res.NumberOfInput*parent.XPath.Length);

            res.NumberIndex = res.NumberOfParagraph + parent.XPath.Length + res.NumberOfTextParagraph +
                              res.NumberOfLongText +
                              res.NumberOfImage + res.TextLenght +
                              res.NumberOfBigImage +
                              res.NumberOfTag +
                              res.NumberOfTitle + res.NumberOfSmallImage + res.NumberOfInput;
            return res;
        }

        /// <summary>
        /// Tính trong đoạn text có bao nhiêu câu
        /// </summary>
        /// <param name="text"></param>
        /// <returns>int</returns>
        public static int GetSentences(string text)
        {
            text = text.Replace("\n", " ").Replace("\r", " ").Replace("\t", " ").Trim();
            int res = 0;
            int nWord = 0;
            for (int i = 0; i < text.Length - 1; ++i)
            {
                if (text[i] == ' ')
                {
                    nWord++;
                }
                if (",.?!;:".IndexOf(text[i]) != -1 && text[i + 1] == ' ' && nWord > 5)
                {
                    res++;
                    nWord = 0;
                }
            }

            return res;
        }

        public HtmlNode GetNodeBody()
        {
            var nodeBody = HtmlDocument.DocumentNode.SelectSingleNode("//body");
            return nodeBody;
        }
    }
}